package net.chrone.tpsdk.quartz.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * SFTP文件上传下载工具类(包括密码和密钥连接)
 */
public class SftpClient {
	
	private static final Logger logger = LoggerFactory.getLogger(SftpClient.class);

	private String username;
	private String password;
	private int port;
	private String host;
	private String priKeyFile;
	private String passphrase;
	private int timeout = Integer.valueOf(PropertiesUtil.getProperty("sftp.fm.open.timeout"));

	private Session session = null;
	private Channel channel = null;
	
	/**
	 * 默认参数从sftp.properties配置文件中读取
	 */
	public SftpClient(){
		this.username = PropertiesUtil.getProperty("sftp.fm.open.username");
		this.password = PropertiesUtil.getProperty("sftp.fm.open.password");
		this.port = Integer.valueOf(PropertiesUtil.getProperty("sftp.fm.open.port"));
		this.host = PropertiesUtil.getProperty("sftp.fm.open.host");
		this.priKeyFile = PropertiesUtil.getProperty("sftp.fm.open.priKeyFile");
		this.passphrase = PropertiesUtil.getProperty("sftp.fm.open.passphrase");
		//this.timeout = Integer.valueOf(PropertiesUtil.getProperty("sftp.fm.open.timeout"));
	}
	/**
	 * @param username
	 * @param password
	 * @param port
	 * @param host
	 */
	public SftpClient(String username, String password, int port, String host) {
		this.username = username;
		this.password = password;
		this.port = port;
		this.host = host;
	}

	/**
	 * @param username
	 * @param password
	 * @param port
	 * @param host
	 * @param priKeyFile
	 * @param passphrase
	 */
	public SftpClient(String username, String password, int port, String host, String priKeyFile,
			String passphrase) {
		this.username = username;
		this.password = password;
		this.port = port;
		this.host = host;
		this.priKeyFile = priKeyFile;
		this.passphrase = passphrase;
	}

	public ChannelSftp connect() {

		JSch jsch = new JSch();
		try {
			if (port > 0) {
				session = jsch.getSession(username, host, port);
			} else {
				session = jsch.getSession(username, host);
			}
			if (session == null) {
				logger.error("获取连接session失败, session is null");
				DingTalkUtil.sendDingMsg("获取连接session失败, session is null");
				return null;
			}
			// 设置登陆主机的密码
			session.setPassword(password);// 设置密码
			Properties sshConfig = new Properties();
			sshConfig.put("StrictHostKeyChecking", "no");
			session.setConfig(sshConfig);
			session.setTimeout(timeout);
			session.connect();
			// 创建sftp通信通道
			channel = session.openChannel("sftp");
			channel.connect();
			return (ChannelSftp) channel;
		} catch (JSchException e) {
			logger.error("密码方式连接SFTP服务器异常：", e);
			DingTalkUtil.sendDingMsg("密码方式连接SFTP服务器异常");
		}
		return null;
	}

	/**
	 * 密钥文件连接
	 * 
	 * @return
	 */

	public ChannelSftp priKeyConnect() {
		JSch jsch = new JSch();
		try {
			if (priKeyFile != null && !"".equals(priKeyFile)) {
				if (passphrase != null && !"".equals(passphrase)) {
					jsch.addIdentity(priKeyFile, passphrase);
				} else {
					jsch.addIdentity(priKeyFile);
				}
			}
			if (port > 0) {
				session = jsch.getSession(username, host, port);
			} else {
				session = jsch.getSession(username, host);
			}
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);
			session.setTimeout(timeout);
			session.connect();
			channel = session.openChannel("sftp");
			channel.connect();
			return (ChannelSftp) channel;
		} catch (JSchException e) {
			logger.error("密钥文件方式连接SFTP服务器异常：", e);
		}
		return null;
	}

	/**
	 * 
	 * @param is
	 *            要上传的本地文件流
	 * @param dsc
	 *            目标目录或文件，若是目录则上传的目标文件名和本地文件名一样
	 * @param sftp
	 * @return
	 */
	public boolean upload(InputStream is, String dsc, ChannelSftp sftp) {
		try {
			sftp.put(is, dsc);
			return true;
		} catch (SftpException e) {
			logger.error("SFTP上传本地文件流异常：", e);
		}
		return false;
	}

	/**
	 * 
	 * @param remotedir
	 *            要上传到的目录
	 * @param uploadFile
	 *            上传的文件
	 * @param sftp
	 * @return
	 */
	public boolean upload(String remotedir, String uploadFile, ChannelSftp sftp) {
		try {
			sftp.cd(remotedir);
			File file = new File(uploadFile);
			sftp.put(new FileInputStream(file), file.getName());
			return true;
		} catch (Exception e) {
			logger.error("SFTP上传异常：", e);
		}
		return false;
	}

	/**
	 * 下载文件
	 * 
	 * @param directory
	 *            下载目录
	 * @param downloadFile
	 *            下载的文件
	 * @param saveFile
	 *            存在本地的文件
	 * @param sftp
	 */
	public boolean download(String directory, String downloadFile, String saveFile, ChannelSftp sftp) {
		try {
			mkdirs(saveFile);
			sftp.cd(directory);
			sftp.get(downloadFile, saveFile);
			return true;
		} catch (Exception e) {
			logger.error("SFTP下载文件异常：", e);
			DingTalkUtil.sendDingMsg("SFTP下载文件异常");
		}
		return false;
	}

	/**
	 * 删除文件
	 * 
	 * @param directory
	 *            要删除文件所在目录
	 * @param deleteFile
	 *            要删除的文件
	 * @param sftp
	 */
	public boolean delete(String directory, String deleteFile, ChannelSftp sftp) {
		try {
			sftp.cd(directory);
			sftp.rm(deleteFile);
			return true;
		} catch (Exception e) {
			logger.error("SFTP删除文件异常：", e);
		}
		return false;
	}
	
	public boolean exists(String directory, String fileName, ChannelSftp sftp) {
		try {
			sftp.cd(directory);
			sftp.lstat(fileName);
			return true;
		} catch (SftpException e) {
			if(e.id == ChannelSftp.SSH_FX_NO_SUCH_FILE){
				logger.error("要下载的对账单文件不存在,文件路径："+directory+"/"+fileName);
				return false;
			}
			logger.error("SFTP检查文件是否存在异常：", e);
		}
		return false;
	}

	public void disconnected(ChannelSftp sftp) {
		if (sftp != null) {
			try {
				sftp.getSession().disconnect();
			} catch (JSchException e) {
				logger.error("关闭session异常：", e);
			}
			sftp.disconnect();
		}
	}
	
	/**
	 * 如果目录不存在就创建目录    
	 * @param path    
	 */
	public void mkdirs(String path){
		File file = new File(path);
		String parentPath = file.getParent();
		File parentFile = new File(parentPath);
		if(!parentFile.exists()){
			parentFile.mkdirs();
		}
		if(file.exists()){
			file.delete();
		}
	}
}